package consoleclient;

import java.io.IOException;
import java.net.BindException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;

public class ConsoleClientReader  implements Runnable {
    private static final int SERVER_PORT = 2004;
    private static final int LOCAL_PORT = 5555;

    private static final int TIME_TO_SLEEP_BEFORE_CLOSING = 1000;

    private StringSocket serverChannel;
    private StringSocket localChannel;
    private String serverName;
    private int localPort;

    public static void main(String[] args) {
        int localPort;
        String host;
        if (args.length == 0) {
            host = "localhost";
            localPort = LOCAL_PORT;
        } else if (args.length == 1) {
            host = args[0];
            localPort = LOCAL_PORT;
        } else {
            host = args[0];
            localPort = Integer.parseInt(args[1]);
        }
        new ConsoleClientReader(host, localPort).run();
    }

    public ConsoleClientReader(String serverName, int localPort) {
        this.serverName = serverName;
        this.localPort = localPort;
    }

    private void sleep_before_exit() {
        try {
            Thread.sleep(TIME_TO_SLEEP_BEFORE_CLOSING);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        try {
            serverChannel = new StringSocket(new Socket(serverName, SERVER_PORT));
            System.out.println("connected to " + serverName + " in port " + SERVER_PORT);
            startWriterListener();
            String message = "";
            do {
                handleMessage(serverChannel.read());
            } while (!message.equals("exit"));
        } catch (UnknownHostException unknownHost) {
            System.err.println("You are trying to connect to an unknown host!");
        } catch (Exception e) {
            System.out.println("Server has disconnected.");
        } finally {
            if (serverChannel != null) serverChannel.close();
            if (localChannel != null) localChannel.close();
        }
    }

    private void handleMessage(String message) throws IOException {
        if (message.startsWith(" ")) {
            String[] info = message.split(" ", 3);
            message = info[2];
            serverChannel.write("!" + info[1]);
        }
        System.out.println(message);
    }

    private void startWriterListener() throws Exception {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    ServerSocket localServerSocket = new ServerSocket(localPort);
                    System.out.println("waiting writer connection");
                    localChannel = new StringSocket(localServerSocket.accept());
                    System.out.println("writer connection is established");
                    localServerSocket.close();
                    while (true) {
                        String message = "";
                        try {
                            message = localChannel.read();
                        } catch (Exception e) {
                            System.out.println("Writer has disconnected.");
                            sleep_before_exit();
                            return;
                        }
                        serverChannel.write(message);
                        if (message.equals("exit")) {
                            localChannel.close();
                            System.exit(0);
                        }
                    }
                } catch (BindException e) {
                    System.out.println("Another client 'reader' console is already running. Terminating.");
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if (localChannel != null) {
                        localChannel.close();
                    }
                }
                sleep_before_exit();
            }
        }).start();
    }
}
